home *** CD-ROM | disk | FTP | other *** search
- /**
- GRAB Graph Layout and Browser System
-
- Copyright (c) 1986, 1988 Regents of the University of California
- Copyright (c) 1989, Tera Computer Company
- **/
-
- /**
- ps.c contains procedures to draw a layed out digraph into a postscript
- file.
-
- Portions of this file were adapted from previously copyrighted material.
- These are denoted by the comments "begin f2ps material" and
- "end f2ps material". The original copyright notice follows:
-
- F2ps : Fig-to-PostScript translator
-
- Copyright (c) 1986 by Supoj Sutanthavibul (supoj@sally.UTEXAS.EDU)
- June 1986.
- 1st revision : March 1988 - read fig 1.4
-
- %W %G%
-
- **/
-
- #include "malloc.h"
- #include <sys/file.h>
- #include <stdio.h>
- #include <pwd.h>
- #include <math.h>
- #include <string.h>
- #include <time.h>
-
- #include "attribute.h"
- #include "digraph.h"
- #include "screen.h"
- #include "globals.h"
- #include "scrdep.h"
- #include "ps.h"
- #include "interf.h"
-
- static FILE *psfile;
- static char psname[MAXSTR];
- static double charxsize; /* character width */
- static double charysize; /* character height */
- static double echarxsize; /* edge label character width */
- static double echarysize; /* edge label character height */
- static double curcharxsize; /* current valid character width */
- static double curcharysize; /* current valid character height */
- #define FUDGE 1.8
- /**
- with variable-sized fonts, you fit more characters in the x
- dimension as the y (given an aspect ratio of one). We can use this
- fudge factor to increase the size of the font and still keep the text
- the proper size
- **/
-
- OUTEDGE *get_edge();
-
- static int llx, lly, urx, ury;
- static double scalex, scaley;
-
- /* begin f2ps material */
-
- #define PAGE_WIDTH 612 /* points; 8.5" */
- #define PAGE_HEIGHT 792 /* points; 11" */
- #define POINT_PER_INCH 72
- #define DEFAULT_FONT "Times-Roman"
-
- char *font = DEFAULT_FONT;
- float cur_thickness;
- BOOL show_page = TRUE;
- BOOL ellipse_exist();
-
- #define TEXT_PS "\
- /%s findfont %f scalefont def\n\
- "
-
- #define BEGIN_PROLOG "\
- /$XgrabpsDict 32 dict def \
- $XgrabpsDict begin\
- $XgrabpsDict /mtrx matrix put\
- "
- #define ELLIPSE_PS " \
- /DrawEllipse {\
- /endangle exch def\
- /startangle exch def\
- /yrad exch def\
- /xrad exch def\
- /y exch def\
- /x exch def\
- /savematrix mtrx currentmatrix def\
- x y translate xrad yrad scale 0 0 1 startangle endangle arc\
- savematrix setmatrix\
- } def\
- "
- #define END_PROLOG "\
- end\
- /$XgrabpsBegin {$XgrabpsDict begin /$XgrabpsEnteredState save def} def\
- /$XgrabpsEnd {$XgrabpsEnteredState restore end} def\
- \n%%EndProlog\
- "
-
- /* end f2ps material */
-
-
- #define LEFT_MARGIN 1 * POINT_PER_INCH /* margins, in points */
- #define RIGHT_MARGIN 1 * POINT_PER_INCH
- #define TOP_MARGIN 1 * POINT_PER_INCH
- #define BOTTOM_MARGIN 1 * POINT_PER_INCH
- #define LABELX 20 /* extra room for edge/node labels */
- #define LABELY 8 /* extra room for edge/node labels */
-
- #define MAXCHT 24.0 /* characters are really obnoxious if they're
- bigger than this */
- #define MAXELHT 8.0 /* edge labels should stay small */
- #define MINCHT 4.0 /* can't read characters with width or height
- smaller than this */
-
- #define DB_MARGIN 2.0 /* distance from inner to outer rectangle
- for a double box node */
-
- #define DEFAULT_PS_FONT "-adobe-times-medium-r-normal--10-100-75-75-p-54-iso8859-1" /* to use fonthandler.c to get a size in the X dimension */
- #define DEFAULT_PS_FONT_SIZE 10.0 /* 10 point font used for sizing */
-
- char *psfont = DEFAULT_PS_FONT;
-
- static BOOL firstText = TRUE;
- static BOOL nodeOnly;
-
- /**
- DrawScreenPS draws what you see on the screen on one page.
- DrawGraphPS draws the entire graph on one page.
- The only differences are the names of the output files and the
- bounding boxes.
- **/
-
- DrawScreenPS(digraph, showbc)
- DIGRAPH* digraph;
- BOOL showbc;
- {
- SCREEN psscreen;
-
- psscreen.absview.min_x = screen.bound.min_x;
- psscreen.absview.min_y = screen.bound.min_y;
- psscreen.absview.max_x = screen.bound.max_x;
- psscreen.absview.max_y = screen.bound.max_y;
-
- DrawPS(digraph, showbc, &psscreen, "screen");
- }
-
- DrawGraphPS(digraph, showbc)
- DIGRAPH* digraph;
- BOOL showbc;
- {
- SCREEN psscreen;
-
- psscreen.absview.min_x = screen.absview.min_x;
- psscreen.absview.min_y = screen.absview.min_y;
- psscreen.absview.max_x = screen.absview.max_x;
- psscreen.absview.max_y = screen.absview.max_y;
-
- DrawPS(digraph, showbc, &psscreen, name);
- }
-
- DrawPS(digraph, showbc, psscreen, fname)
- DIGRAPH *digraph;
- BOOL showbc; /* flag to show bc's */
- SCREEN *psscreen;
- char *fname;
- /**
- write the portion of the graph denoted by psscreen in postscript format
- in file fname
- **/
- {
- NODE *node; /* each node */
- int cx, cy;
- char *s;
-
- if (digraph == NULL)
- {
- IChangeStatusLine("No digraph to draw", FALSE);
- return;
- }
-
- (void) strncpy(psname, fname, MAXSTR - 4);
- (void) strcat(psname, ".ps");
-
- s = (char *) malloc(sizeof(char) * MAXLINE);
-
- if ((psfile = fopen(psname, "r")) != NULL)
- {
- fclose(psfile);
- sprintf(s, "File %s exists. Overwrite?", psname);
-
- if (IConfirm(s) != 'y')
- {
- return;
- }
- }
-
- if ((psfile = fopen(psname, "w")) == NULL)
- {
- sprintf(s, "Couldn't open %s", psname);
- IChangeStatusLine(s, FALSE);
- dispose(s);
- return;
- }
-
- firstText = TRUE;
- nodeOnly = FALSE;
- cur_thickness = 0.0;
-
- if (landscapePSFile)
- /* draw in 'landscape' mode (sideways) */
- {
- llx = BOTTOM_MARGIN;
- lly = RIGHT_MARGIN + LABELY;
- urx = PAGE_HEIGHT - (TOP_MARGIN + LABELX);
- ury = PAGE_WIDTH - LEFT_MARGIN;
- }
- else
- {
- llx = LEFT_MARGIN;
- lly = BOTTOM_MARGIN + LABELY;
- urx = PAGE_WIDTH - (RIGHT_MARGIN + LABELX);
- ury = PAGE_HEIGHT - TOP_MARGIN;
- }
-
- psscreen->display.min_x = 0;
- psscreen->display.min_y = 0;
- psscreen->display.max_x = urx - llx;
- psscreen->display.max_y = ury - lly;
-
- psscreen->canvas.min_x = llx;
- psscreen->canvas.min_y = lly;
- psscreen->canvas.max_x = urx;
- psscreen->canvas.max_y = ury;
-
- psscreen->zoom.xzoom = (float) (psscreen->absview.max_x -
- psscreen->absview.min_x) /
- (float) (psscreen->canvas.max_x -
- psscreen->canvas.min_x);
- psscreen->zoom.yzoom = (float) (psscreen->absview.max_y -
- psscreen->absview.min_y) /
- (float) (psscreen->canvas.max_y -
- psscreen->canvas.min_y);
-
- psscreen->bound.min_x = SCRX_TO_ABSX(psscreen, llx);
- psscreen->bound.min_y = SCRY_TO_ABSY(psscreen, lly);
- psscreen->bound.max_x = SCRX_TO_ABSX(psscreen, urx);
- psscreen->bound.max_y = SCRY_TO_ABSY(psscreen, ury);
-
- scaley = psscreen->zoom.yzoom;
- scalex = psscreen->zoom.xzoom;
-
- cy = get_height(digraph);
- cx = HALF_CHAR * 2;
- charysize = (double) cy * 0.75 / scaley;
- /* characters are at most about 3/4 of the box */
-
- /* can't be too big for x, after x is resized */
- if (charysize > (cx * FUDGE / scalex))
- {
- charysize = cx * FUDGE / scalex;
- }
-
- if ((charysize < MINCHT) && printNodeLabel)
- {
- nodeOnly = TRUE; /* only want to see the nodes */
- charysize = MINCHT;
- }
- else if (charysize > MAXCHT)
- {
- charysize = MAXCHT; /* don't want text too big */
- }
-
- charxsize = charysize;
-
- if (charysize > MAXELHT) /* don't want edge labels too big */
- {
- echarysize = MAXELHT;
- }
- else
- {
- echarysize = charysize;
- }
-
- echarxsize = echarysize;
-
- ISetPS(psfont);
- curcharxsize = charxsize;
- curcharysize = charysize;
-
- /* begin f2ps material */
- prolog(digraph);
- /* end f2ps material */
-
- fprintf(psfile, "Nodefont setfont\n");
-
- each_node(digraph, node)
- loop
- ps_draw_node(digraph, node, showbc, psscreen);
- ps_draw_out_edges(digraph, node, psscreen);
- /**
- don't need to draw the in edges as we have already drawn all
- the edges by drawing the out edges
- **/
- endloop
-
- /* begin f2ps material */
- epilog();
- /* end f2ps material */
-
- ps_close(psfile);
-
- sprintf(s, "%s created.", psname);
- IChangeStatusLine(s, FALSE);
- dispose(s);
- } /* DrawPS */
-
- ps_draw_node(digraph, node, showbc, psscreen)
- DIGRAPH *digraph;
- NODE *node; /* node to draw */
- BOOL showbc; /* flag to show bc's */
- SCREEN *psscreen;
- /**
- ps_draw_node draws a node, including its name, outgoing edges, and
- barycenters (optional).
- **/
- {
- switch (Shape(node))
- {
- case POINT:
- break;
- case OVAL:
- ps_draw_oval((float) ABSX_TO_SCRX(psscreen, X_position(node)),
- (float) ABSY_TO_SCRY(psscreen, Y_position(node)),
- (float) SCALE_X(psscreen, Half_width(node)),
- (float) SCALE_Y(psscreen, Half_height(node)),
- Brush(node), Color(node));
- break;
- case CIRCLE:
- ps_draw_oval((float) ABSX_TO_SCRX(psscreen, X_position(node)),
- (float) ABSY_TO_SCRY(psscreen, Y_position(node)),
- (float) SCALE_Y(psscreen, Half_height(node)),
- (float) SCALE_Y(psscreen, Half_height(node)),
- Brush(node), Color(node));
- break;
- case DIAMOND:
- ps_draw_diamond((float) ABSX_TO_SCRX(psscreen, X_position(node)),
- (float) ABSY_TO_SCRY(psscreen, Y_position(node)),
- (float) ABSX_TO_SCRX(psscreen, X_left(node)),
- (float) ABSY_TO_SCRY(psscreen, Y_bottom(node)),
- (float) ABSX_TO_SCRX(psscreen, X_right(node)),
- (float) ABSY_TO_SCRY(psscreen, Y_top(node)),
- Brush(node), Color(node));
- break;
- case DOUBLE_BOX:
- /**
- without the MINs and MAXs, it's possible for the top
- of the inner rectangle to be below the bottom, and/or the
- right to be to the left of the left (if the rectangle is
- very short or very skinny)
- **/
- ps_draw_rect(MIN((float) (ABSX_TO_SCRX(psscreen, X_left(node)) +
- (float) DB_MARGIN),
- (float) (ABSX_TO_SCRX(psscreen,
- X_position(node)))),
- MAX((float) (ABSX_TO_SCRX(psscreen, X_right(node)) -
- (float) DB_MARGIN),
- (float) (ABSX_TO_SCRX(psscreen,
- X_position(node)))),
- MIN((float) (ABSY_TO_SCRY(psscreen, Y_bottom(node)) +
- (float) DB_MARGIN),
- (float) (ABSY_TO_SCRY(psscreen,
- Y_position(node)))),
- MAX((float) (ABSY_TO_SCRY(psscreen, Y_top(node)) -
- (float) DB_MARGIN),
- (float) (ABSY_TO_SCRY(psscreen,
- Y_position(node)))),
- Brush(node), Color(node));
-
- ps_draw_rect((float) ABSX_TO_SCRX(psscreen, X_left(node)),
- (float) ABSX_TO_SCRX(psscreen, X_right(node)),
- (float) ABSY_TO_SCRY(psscreen, Y_bottom(node)),
- (float) ABSY_TO_SCRY(psscreen, Y_top(node)),
- Brush(node), Color(node));
- break;
- case RECTANGLE:
- ps_draw_rect((float) ABSX_TO_SCRX(psscreen, X_left(node)),
- (float) ABSX_TO_SCRX(psscreen, X_right(node)),
- (float) ABSY_TO_SCRY(psscreen, Y_bottom(node)),
- (float) ABSY_TO_SCRY(psscreen, Y_top(node)),
- Brush(node), Color(node));
- break;
- default:
- perror("ps_draw_node: illegal shape");
- break;
- }
-
- if (!(Is_dummy(node)))
- {
- if (nodeOnly)
- /**
- if the text doesn't fit in the node, put it just below it and
- to the right.
- **/
- {
- if (Shape(node) == CIRCLE)
- {
- ps_text(Text(node),
- (double) ABSX_TO_SCRX(psscreen, X_position(node)) +
- (double) SCALE_Y(psscreen, Half_height(node)),
- (double) ABSY_TO_SCRY(psscreen, Y_bottom(node)),
- TOPLEFT, Color(node));
- }
- else
- {
- ps_text(Text(node),
- (double) ABSX_TO_SCRX(psscreen, X_right(node)),
- (double) ABSY_TO_SCRY(psscreen, Y_bottom(node)),
- TOPLEFT, Color(node));
- }
- }
- else
- /* otherwise, center it */
- {
- ps_text(Text(node),
- (double) ABSX_TO_SCRX(psscreen, X_position(node)),
- (double) ABSY_TO_SCRY(psscreen, Y_position(node)),
- CENTCENT, Color(node));
- }
- }
-
- if (showbc && !nodeOnly)
- {
- ps_draw_barycenters(node, Color(node), psscreen);
- }
- } /* ps_draw_node */
-
-
- ps_draw_barycenters(node, color, psscreen)
- NODE *node;
- COLOR color;
- SCREEN *psscreen;
- /**
- ps_draw_barycenters displays the priorities and barycenters above and
- below a node.
- **/
- {
- char bc[20]; /* up or down bc */
-
- if (Bc(node, UP) != NO_BC)
- {
- sprintf(bc, "%d/%3.1f", Priority(node, UP), Bc(node, UP));
- ps_text(bc,
- (double) ABSX_TO_SCRX(psscreen, X_position(node)),
- (double) ABSY_TO_SCRY(psscreen, Y_top(node)),
- CENTCENT, color);
- }
-
- if (Bc(node, DOWN) != NO_BC)
- {
- sprintf(bc, "%d/%3.1f", Priority(node, DOWN), Bc(node, DOWN));
- ps_text(bc,
- (double) ABSX_TO_SCRX(psscreen, X_position(node)),
- (double) ABSY_TO_SCRY(psscreen, Y_bottom(node)),
- CENTCENT, color);
- }
- } /* draw_barycenters */
-
- ps_draw_out_edges(digraph, node, psscreen)
- DIGRAPH *digraph;
- NODE *node; /* node with edges */
- SCREEN *psscreen;
- /* draw all the out edges of a node */
- {
- VNO to_vno; /* each succedent node */
- NODE *tonode, *get_prev_node(), *get_next_node();
- double from_x;
- double from_y;
- double to_x;
- double to_y;
- BOOL forward;
- BOOL reversed;
- BRUSH brush;
- COLOR color;
- OUTEDGE *e;
- int i;
-
- each_element(Succ_set(node), to_vno)
- loop
- tonode = Node(digraph, to_vno);
-
- for (i = max_edges(node, tonode); i > 0; i--)
- {
- forward = FALSE;
- reversed = FALSE;
-
- /* clip in both directions */
- if ((e = get_edge(digraph, node, tonode, i)) != NULL)
- {
- Clip(node, tonode, i, &from_x, &from_y, &to_x, &to_y, psscreen);
-
- /**
- should we draw the arrow forward, reversed, or not at
- all? outedge_reversed is false if the first node is a
- dummy node, so an edge from a dummy node will only have
- an arrow if tonode isn't a dummy node and the edge isn't
- reversed.
- **/
- if (printArrow)
- {
- if (outedge_reversed(digraph, node, tonode, i))
- {
- reversed = TRUE;
- }
- else if (!Is_dummy(tonode))
- {
- NODE *prevnode;
-
- if (Is_dummy(node))
- {
- prevnode = get_prev_node(digraph, node);
- }
- else
- {
- prevnode = node;
- }
-
- if (!outedge_reversed(digraph, prevnode, tonode, i))
- {
- forward = TRUE;
- }
- }
- }
-
- brush = Brush(e);
- color = Color(e);
-
- ps_line((double) ABSX_TO_SCRX(psscreen, from_x),
- (double) ABSY_TO_SCRY(psscreen, from_y),
- (double) ABSX_TO_SCRX(psscreen, to_x),
- (double) ABSY_TO_SCRY(psscreen, to_y),
- reversed, forward, brush, color);
-
- if (!Is_dummy(node) && printEdgeLabel && !nodeOnly)
- {
- ps_draw_edge_label(digraph, node, tonode, i,
- (double) ABSX_TO_SCRX(psscreen, from_x),
- (double) ABSY_TO_SCRY(psscreen, from_y),
- (double) ABSX_TO_SCRX(psscreen, to_x),
- (double) ABSY_TO_SCRY(psscreen, to_y),
- color);
- }
- }
- }
- endloop
- } /* draw_out_edges */
-
- ps_draw_edge_label(digraph, node, tonode, ord, from_x, from_y, to_x, to_y,
- color)
- DIGRAPH *digraph;
- NODE *node, *tonode;
- int ord;
- double from_x, from_y, to_x, to_y;
- COLOR color;
- {
- char *label;
- double xpos, ypos, shift;
- NODE *get_next_node();
- char *get_edge_label();
-
- if (Is_dummy(tonode))
- {
- tonode = get_next_node(digraph, tonode);
- }
-
- label = get_edge_label(digraph, node, tonode, ord);
-
- if (*label != '\0')
- {
- /**
- multigraph support: labels for edges should be staggered so
- they don't overrun each other
- **/
- shift = echarysize * (ord / 2) * ((ord % 2 == 0) ? -1 : 1);
-
- xpos = (double) (from_x + to_x) / 2.0;
- ypos = (double) (from_y + to_y) / 2.0;
-
- if (from_y != to_y)
- {
- ypos += shift;
- xpos += shift * (from_x - to_x) / (from_y - to_y);
- }
-
- curcharxsize = echarxsize;
- curcharysize = echarysize;
-
- fprintf(psfile, "Edgefont setfont\n");
- ps_text(label, xpos, ypos, CENTLEFT, color);
- fprintf(psfile, "Nodefont setfont\n");
-
- curcharxsize = charxsize;
- curcharysize = charysize;
- }
- }
-
- ps_close(fp)
- FILE *fp;
- /* close the file */
- {
- if (fp == (FILE *) NULL)
- {
- fprintf(stderr, "ps_close: NULL file pointer\n");
- }
-
- fclose(fp);
- }
-
- ps_text(text, x, y, justification, color)
- char *text; /* text string */
- double x, y; /* justification relative to this point */
- int justification; /* type of justification */
- COLOR color;
- /* draw the text at position <x, y> with the given color and justification */
- {
- char *c;
- double length; /* length based on size */
- double pos_x, pos_y; /* lower left coordinate position of text */
-
- if (strlen(text) == 0)
- {
- return;
- }
- else if ((justification < BOTLEFT) || (justification > BOTCENT) ||
- ((justification > CENTCENT) && (justification < TOPLEFT)))
- {
- fprintf(stderr, "ps_text: bad justification %d\n", justification);
- }
-
- length = IWidthPS(text) * curcharxsize / DEFAULT_PS_FONT_SIZE;
- /* call fonthandler.c to find the size of the text */
-
- switch (justification)
- {
- case BOTLEFT:
- case CENTLEFT:
- case TOPLEFT:
- pos_x = x;
- break;
- case BOTCENT:
- case CENTCENT:
- case TOPCENT:
- pos_x = x - (length / 2.0);
- break;
- case BOTRIGHT:
- case CENTRIGHT:
- case TOPRIGHT:
- pos_x = x - length;
- break;
- }
-
- switch (justification)
- {
- case BOTLEFT:
- case BOTCENT:
- case BOTRIGHT:
- pos_y = y;
- break;
- case CENTLEFT:
- case CENTCENT:
- case CENTRIGHT:
- pos_y = y - (curcharysize / 2.0);
- break;
- case TOPLEFT:
- case TOPCENT:
- case TOPRIGHT:
- pos_y = y - curcharysize;;
- break;
- }
-
- /* begin f2ps material */
- set_style(SOLIDB, color);
- fprintf(psfile, "%f %f moveto (", pos_x, pos_y);
-
- for (c = text; *c; c++)
- {
- if (*c == '\\' || *c == '(' || *c == ')')
- {
- putc('\\', psfile);
- }
-
- putc(*c, psfile);
- }
-
- fprintf(psfile, ") show\n");
-
- reset_style(SOLIDB, color);
- }
-
- prolog(digraph)
- DIGRAPH *digraph;
- /* write the introductory postscript magic */
- {
- char host[MAXSTR];
- struct passwd *who;
- long when;
- extern char *ctime();
- extern long time();
-
- fprintf(psfile, "%%!PS-Adobe-1.0\n"); /* PostScript magic strings */
- who = getpwuid(getuid());
-
- if (-1 == gethostname(host, sizeof(host)))
- {
- (void)strcpy(host, "unknown-host!?!?");
- }
-
- (void) time(&when);
- fprintf(psfile, "%%%%Title: %s\n", name);
- fprintf(psfile, "%%%%Creator: Xgrab\n");
- fprintf(psfile, "%%%%CreationDate: %s", ctime(&when));
- fprintf(psfile, "%%%%For: %s@%s (%s)\n", who->pw_name, host, who->pw_gecos);
- fprintf(psfile, "%%%%Pages: %d\n", 1);
- fprintf(psfile, "%%%%BoundingBox: %d %d %d %d\n", llx, lly, urx, ury);
- fprintf(psfile, "%%%%EndComments\n");
- fprintf(psfile, "%s\n", BEGIN_PROLOG);
-
- fprintf(psfile, "/Nodefont");
- fprintf(psfile, TEXT_PS, font, charysize);
- fprintf(psfile, "/Edgefont");
- fprintf(psfile, TEXT_PS, font, echarysize);
-
- if (ellipse_exist(digraph))
- {
- fprintf(psfile, "%s\n", ELLIPSE_PS);
- }
-
- fprintf(psfile, "%s\n", END_PROLOG);
- fprintf(psfile, "$XgrabpsBegin\n");
-
- if (landscapePSFile)
- {
- fprintf(psfile, "%d 0 translate 90 rotate\n", PAGE_WIDTH);
- }
- /* end f2ps material */
-
- /* clipping box */
- fprintf(psfile, "newpath %d %d moveto ", llx - 1, lly - LABELY - 1);
- fprintf(psfile, "%d %d lineto ", urx + LABELX + 1, lly - LABELY - 1);
- fprintf(psfile, "%d %d lineto ", urx + LABELX + 1, ury + 1);
- fprintf(psfile, "%d %d lineto ", llx - 1, ury + 1);
- fprintf(psfile, "%d %d lineto clip\n", llx - 1, lly - LABELY - 1);
- }
-
- /* begin f2ps material */
-
- epilog()
- /* write the ending postscript magic */
- {
- if (show_page)
- {
- fprintf(psfile, "showpage\n");
- }
-
- fprintf(psfile, "$XgrabpsEnd\n");
- }
-
- set_style(b, c)
- BRUSH b;
- COLOR c;
- /* set the brush and color */
- {
- if (b == DASHEDB || b == BDASHEDB)
- {
- fprintf(psfile, "\t[%d] 0 setdash\n", 4);
- }
- else if (b == DOTTEDB || b == BDOTTEDB)
- {
- fprintf(psfile, "\t[%d] 0 setdash\n", 1);
- }
-
- if (c == GRAY)
- {
- fprintf(psfile, "\t.5 setgray\n");
- }
- else if (c == WHITE)
- {
- fprintf(psfile, "\t1 setgray\n");
- }
- }
-
- reset_style(b, c)
- /* change the brush and color back to normal */
- BRUSH b;
- COLOR c;
- {
- if (b == DASHEDB || b == DOTTEDB || b == BDASHEDB || b == BDOTTEDB)
- {
- fprintf(psfile, "\t[] 0 setdash\n");
- }
-
- if (c == GRAY || c == WHITE)
- {
- fprintf(psfile, "\t0 setgray\n");
- }
- }
-
- set_linewidth(b)
- BRUSH b;
- /* set the thickness of the lines drawn */
- {
- float w;
-
- if (b == BSOLIDB || b == BDASHEDB || b == BDOTTEDB)
- {
- w = 3.0;
- }
- else
- {
- w = 0.2;
- }
-
- if (w != cur_thickness)
- {
- cur_thickness = w;
- fprintf(psfile, "%.3f setlinewidth\n", 0.4 * cur_thickness);
- }
- }
-
- ps_line(fromx, fromy, tox, toy, reversed, forward, brush, color)
- double fromx, fromy, tox, toy;
- BOOL reversed, forward;
- BRUSH brush;
- COLOR color;
- /* draw a line */
- {
- set_linewidth(brush);
- set_style(brush, color);
-
- if (reversed)
- {
- draw_arrow_head(tox, toy, fromx, fromy);
- }
-
- fprintf(psfile, "%% Polyline\n");
- fprintf(psfile, "newpath %f %f moveto", fromx, fromy);
- fprintf(psfile, " %f %f lineto stroke\n", tox, toy);
-
- if (forward)
- {
- draw_arrow_head(fromx, fromy, tox, toy);
- }
-
- reset_style(brush, color);
- }
-
-
- ps_arc(centerx, centery, x1, y1, x2, y2, reversed, forward, brush, color)
- double centerx, centery, x1, y1, x2, y2;
- BOOL reversed, forward;
- BRUSH brush;
- COLOR color;
- /* draw an arc */
- {
- double angle1, angle2, dx, dy, radius, x, y;
- int direction;
-
- direction = 1; /* counterclockwise */
-
- set_linewidth(brush);
- set_style(brush, color);
-
- if (forward)
- {
- arc_tangent(centerx, centery, x2, y2, direction, &x, &y);
- draw_arrow_head(x, y, x2, y2);
- }
-
- if (reversed)
- {
- arc_tangent(centerx, centery, x1, y1, !direction, &x, &y);
- draw_arrow_head(x, y, x1, y1);
- }
-
- dx = centerx - x1;
- dy = centery - y1;
- radius = sqrt(dx*dx + dy*dy);
- angle1 = atan2(y1-centery, x1-centerx) * 180 / M_PI;
- angle2 = atan2(y2-centery, x2-centerx) * 180 / M_PI;
-
- /* direction = 1 -> Counterclockwise */
- fprintf(psfile, "newpath %.3f %.3f %.3f %.3f %.3f %s stroke\n",
- centerx, centery, radius, angle1, angle2,
- ((direction == 1) ? "arc" : "arcn"));
- reset_style(brush, color);
- }
-
- arc_tangent(x1, y1, x2, y2, direction, x, y)
- double x1, y1, x2, y2, *x, *y;
- int direction;
- {
- if (direction) /* counter clockwise */
- {
- *x = x2 + (y2 - y1);
- *y = y2 - (x2 - x1);
- }
- else
- {
- *x = x2 - (y2 - y1);
- *y = y2 + (x2 - x1);
- }
- }
-
- #define DEFAHT 40.0
- #define DEFAWID 40.0
- #define MINAHT 2.0
- #define MINAWID 2.0
-
- draw_arrow_head(x1, y1, x2, y2)
- double x1, y1, x2, y2;
- /* draw an arrow on the line heading from (x1, y1) to (x2, y2) */
- {
- float x, y, xb, yb, dx, dy, l, sina, cosa;
- float xc, yc, xd, yd;
- float arrowht, arrowwid;
-
- arrowht = DEFAHT / scaley > MINAHT ? DEFAHT / scaley : MINAHT;
- arrowwid = DEFAWID / scalex > MINAWID ? DEFAWID / scalex : MINAWID;
-
- dx = x2 - x1; dy = y1 - y2;
- l = sqrt((double)(dx*dx + dy*dy));
- sina = dy / l; cosa = dx / l;
- xb = x2 *cosa - y2 *sina;
- yb = x2 *sina + y2 *cosa;
- x = xb - arrowht;
- y = yb - arrowwid / 2;
- xc = x*cosa + y*sina;
- yc = -x*sina + y*cosa;
- y = yb + arrowwid / 2;
- xd = x*cosa + y*sina;
- yd = -x*sina + y*cosa;
- fprintf(psfile,
- "newpath %.3f %.3f moveto %f %f lineto %.3f %.3f lineto stroke\n",
- xc, yc, x2, y2, xd, yd);
- }
-
- BOOL ellipse_exist(digraph)
- DIGRAPH *digraph;
- /* return TRUE if there's an ellipse or circle in the graph */
- {
- NODE *node;
-
- each_node(digraph, node)
- loop
- if (Shape(node) == OVAL || Shape(node) == CIRCLE)
- {
- return(TRUE);
- }
- endloop
-
- return(FALSE);
- }
-
- ps_draw_oval(x_pos, y_pos, x_rad, y_rad, brush, color)
- float x_pos, y_pos, x_rad, y_rad; /* center and radius */
- BRUSH brush;
- COLOR color;
- /* draw an ellipse (circles are ellipses) */
- {
- set_linewidth(brush);
- set_style(brush, color);
- fprintf(psfile, "%% Ellipse\n");
- fprintf(psfile, "newpath %f %f %f %f 0 360 DrawEllipse stroke\n",
- x_pos, y_pos, x_rad, y_rad);
- reset_style(brush, color);
- }
-
- ps_draw_rect(left, right, down, up, brush, color)
- float left, right, down, up;
- BRUSH brush;
- COLOR color;
- /* draw a rectangle */
- {
- set_linewidth(brush);
- set_style(brush, color);
-
- fprintf(psfile, "%% Polyline\n");
- fprintf(psfile, "newpath %f %f moveto", right, down);
- fprintf(psfile, " %f %f lineto", right, up);
- fprintf(psfile, " %f %f lineto", left, up);
- fprintf(psfile, " %f %f lineto", left, down);
- fprintf(psfile, " %f %f lineto stroke\n", right, down);
-
- reset_style(brush, color);
- }
-
- ps_draw_diamond(xcenter, ycenter, left, down, right, up, brush, color)
- float xcenter, ycenter, left, right, down, up;
- BRUSH brush;
- COLOR color;
- /* draw a diamond */
- {
- set_linewidth(brush);
- set_style(brush, color);
-
- fprintf(psfile, "%% Polyline\n");
- fprintf(psfile, "newpath %f %f moveto", right, ycenter);
- fprintf(psfile, " %f %f lineto", xcenter, down);
- fprintf(psfile, " %f %f lineto", left, ycenter);
- fprintf(psfile, " %f %f lineto", xcenter, up);
- fprintf(psfile, " %f %f lineto stroke\n", right, ycenter);
-
- reset_style(brush, color);
- }
-
- /* end f2ps material */
-